#pragma once

#include <iostream>
#include <string>
#include <unordered_map>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>//struct sockaddr
#include <netinet/in.h>

using namespace std;

class User
{
public:
    User(string& ip, uint16_t port)
    : _ip(ip),
      _port(port)
    {}

    string getIp()
    {
        return _ip;
    }

    uint16_t getPort()
    {
        return _port;
    }

private:
    string _ip;
    uint16_t _port;
};

class OnlineUser
{
public:
    void addUser(string& ip, uint16_t port)
    {
        string id = ip + "-" + to_string(port);
        _users.insert(make_pair(id, User(ip, port)));
    }

    void delUser(string& ip, uint16_t port)
    {
        string id = ip + "-" + to_string(port);
        _users.erase(id);
    }

    bool isOnline(string& ip, uint16_t port)
    {
        string id = ip + "-" + to_string(port);
        return _users.find(id) != _users.end();
    }

    void broadcastMessage(string& ip, uint16_t port, string& message, int sockfd)
    {
        for (auto& user : _users)
        {
            struct sockaddr_in client;
            client.sin_family = AF_INET;
            client.sin_port = htons(user.second.getPort());
            client.sin_addr.s_addr = inet_addr(user.second.getIp().c_str());
            string response_message = ip + "[" + to_string(port) + "]# ";
            response_message += message;
            sendto(sockfd, response_message.c_str(), response_message.size(), 0, (struct sockaddr*)&client, sizeof client);
        }
    }

private:
    unordered_map<string, User> _users;
};
